#include "Socket.h"
#include "sock.h"
#include "Sockaddr.h"
#include "log/Logger.h"
#include "wrap/socket.h"
#include "wrap/unistd.h"

Socket::~Socket() {
    Wrap::close_(_fd);
}

int Socket::accept(Sockaddr &peer) const {
    struct sockaddr_in addr {};
    const auto fd = Sock::accept(addr, _fd);
    if (fd >= 0) {
        peer.set_sock_addr(addr);
    }
    return fd;
}

void Socket::bind(const Sockaddr &local) const {
    Sock::bind(_fd, local.sock_addr());
}

void Socket::keep_alive(bool option) const {
    Sock::set_socket_option(_fd, SO_KEEPALIVE, static_cast<int>(option));
}

void Socket::listen() const {
    if (Wrap::listen_(_fd, SOMAXCONN) < 0) {
        LOG_SYSFATAL << "listen_";
    }
}

void Socket::reuse_addr(bool option) const {
    Sock::set_socket_option(_fd, SO_REUSEADDR, static_cast<int>(option));
}

void Socket::reuse_port(bool option) const {
#ifdef SO_REUSEPORT
    if (option && Sock::set_socket_option(_fd, SO_REUSEPORT, static_cast<int>(option)) < 0) {
        LOG_SYSERROR << "SO_REUSEPORT failed";
    }

#else
    if (option) {
        LOG_ERROR << "SO_REUSEPORT is no supported";
    }
#endif

}

void Socket::shutdown_write() const {
    if (Wrap::shutdown_ (_fd, SHUT_WR) < 0) {
        LOG_SYSERROR << "shutdown_";
    }
}

